/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */

/*
 * Copyright 2020-2030 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitee.minimalismstyle.fresh.gateway.handler

import com.google.code.kaptcha.impl.DefaultKaptcha
import com.gitee.minimalismstyle.fresh.common.core.const.CacheConst
import com.gitee.minimalismstyle.fresh.common.core.domain.R
import org.springframework.data.redis.core.StringRedisTemplate
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.util.FastByteArrayOutputStream
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import reactor.core.publisher.Mono
import reactor.kotlin.core.publisher.toMono
import java.util.concurrent.TimeUnit
import javax.imageio.ImageIO

/**
 * 生成验证码
 * @author maoxiaodong
 */
@RestController
@RequestMapping("/captcha")
class CaptchaHandler(val redisTemplate: StringRedisTemplate,
                     val kaptcha: DefaultKaptcha) {

    @GetMapping
    fun getCaptcha(@RequestParam(CacheConst.CAPTCHA_TOKEN_KEY) captchaToken: String):
            Mono<ResponseEntity<ByteArray>> {
        //生成验证码
        val text = kaptcha.createText()
        val image = kaptcha.createImage(text)

        //保存验证码信息
        val key = "${CacheConst.CAPTCHA_TOKEN_KEY}_$captchaToken"
        redisTemplate.opsForValue().set(key, text, 3000L, TimeUnit.SECONDS)

        // 转换流信息写出
        val os = FastByteArrayOutputStream()
        ImageIO.write(image, "jpeg", os)
        var headers = HttpHeaders()
        headers.contentType = MediaType.IMAGE_JPEG
        return Mono.just(ResponseEntity(os.toByteArray(), headers, HttpStatus.OK))
    }

    /**
     * 验证码校验
     * @param captchaToken
     * @param captcha
     * @return
     */
    @GetMapping("check")
    fun check(@RequestParam(CacheConst.CAPTCHA_TOKEN_KEY) captchaToken: String, captcha: String): Mono<R<Any>> {
        return checkCaptcha(captchaToken, captcha).toMono()
    }

    fun checkCaptcha(captchaToken: String, captcha: String, isDel: Boolean = false): R<Any> {

        if (captchaToken.isEmpty()) {
            return R.error("验证码token不能为空")
        }

        if (captcha.isEmpty()) {
            return R.error("验证码不能为空")
        }

        val key = "${CacheConst.CAPTCHA_TOKEN_KEY}_$captchaToken"
        if (!redisTemplate.hasKey(key)) {
            return R.error("验证码无效")
        }

        if (!redisTemplate.hasKey(key)) {
            return R.error("验证码无效")
        }

        val validCaptcha: String = redisTemplate.opsForValue().get(key)!!

        return if (validCaptcha.equals(captcha, ignoreCase = true)) {
            if(isDel){
                redisTemplate.delete(key)
            }
            R.success()
        }else{
            R.error("验证码不正确")
        }

    }
}
